iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 6
1
自我挑戰組

React初心者30天的探索之路系列 第 6

[Day 06] 一磚一瓦-React Component

  • 分享至 

  • xImage
  •  

Component的概念就很像一塊塊積木,可以拼湊組成城堡或是飛船之類的,Component裡頭會回傳React element,透過這些Component就可以組成網頁的UI畫面,可以依照需求來切分不同功能的Component,一個Component結構可以很簡單,裡面甚至只有一個按鈕,這時候就會有個疑問?拆分的這麼細有什麼好處嗎?最大的好處就是相似的結構可以抽離出來重複使用,不需要重複的邏輯寫好多遍,也方便維護,有了Component就可以解決以下的問題:

情境一

傳統的寫法為每個頁面都有一個header,假設網頁的header需要改動,就要打開每個頁面header調整,真的會吐血..

情境二

a頁面、b頁面、c頁面都需要這個按鈕,然後功能還一模一樣,重複的東西居然要寫三遍…

Component會定義這個組件的結構樣式等等,再透過外部傳進的資料,根據資料的變化,來更動UI畫面,不需要像傳統那樣手動更新。React Component的有兩種寫法 Class Component以及 Functional Component,今天先來介紹Class component,利用 ES6 Class的語法來創建Class Component,既然提到了Class就花點時間稍微簡介一下Class有哪些方法吧!

constructor建構式

在Class 物件被建立時會呼叫一次,物件的屬性會在這裡做定義,這裡也可以帶入不同的參數來建立不同的類別,那可以不寫嗎?答案是可以的,沒寫也會預設幫你創建constructor

class Bird{ 
 constructor(name){
  this.name = name
 }
}
const bird1 = new Bird('kerry')
const bird2 = new Bird('bay')

extends繼承

先宣告一個父類別(鳥類),並且一定義一個飛行的函式,接者子類別(老鷹)繼承父類別,就可以使用父類別定義的方法。

class Bird{ 
  fly(){
   console.log('fly')
  }
}
class Eagle{
}
const eagle = new Eagle()
eagle.fly() // 印出fly

假如子類別定義了與父類別相同的函式名稱,那麼子類別的函式就會取代父類別的函式

class Bird{ 
  fly(){
   console.log('Birdfly')
  }
}
class Eagle{
  fly(){
   console.log('Eaglefly')
 }
}
const eagle = new Eagle()
eagle.fly() // Eaglefly

那假設我想要在子類別的呼叫父類別的方法可以嗎?就是super()登場的時候了,為了可以取得父類別的屬性或是方法會在constructor呼叫super()方法,這麼一來子類別不需要重寫一遍this.name = name,只要super(name)即可,利用super.函式名稱就可以呼叫父類別的方法。

class Bird{ 
  constructor(name){
   this.name = name
 }  
 fly(){
   console.log('Birdfly')
 }
}
class Eagle{
  constructor(name){
   super(name)
 }
 fly(){
   super.fly()
   console.log('Eaglefly')
 }
}
const eagle = new Eagle()
eagle.fly() // 輸出Birdfly Eaglefly

靜態方法static

屬於class的屬性或方法,不需要實例化,就能以 class名稱.方法來呼叫

class Bird(){ 
  static diss(name){
   console.log('diss ' + name )
 }
}
Bird.diss('mel') //輸出diss mel
const bird = new Bird()
bird.diss('mel) //bird.diss is not a function

了解了Class類別之後就可以來創建React Component,要先import React Component

import React, { Component } from 'react';

然後宣告一個Class,記得命名要跟檔名一致,第一個字都為大寫,並且繼承React Component

class ComponentExample extends Component{
    constructor(props){
        this.super(props)
        this.state = { count: 0 }
    }
    render(){
        return(
            <div>
                <h1>{this.props.name}</h1>
            </div>
        )
    }
}

export default ComponentExample

constructor() 方法,必須先執行super(),才能取得this,會在這裡設定state的初始值,在參考範例的時候,我發現了一件事,為什麼有的範例有寫super(props),有的沒有呢? 而且沒寫的話在render也可以拿到this.props,查了資料原來不管有沒有寫super(props),在render階段都可以用this.props

剛好在爬文的時候看到有網友分享有沒有加super(props)的差異,個人覺得蠻清楚的

什麼都沒寫的

constructor() {
 super()
 console.log(this.props)//undefined
 console.log(props)//error
}

無法取得 this.props

constructor(props) {
 super()
 console.log(this.props)//undefined
 console.log(props)//{}
}

成功取得this.props!

constructor(props) {
 super(props)
 console.log(this.props)//{}
 console.log(props)//{}
}

這樣看起來如果要在constructor階段取得this.props還是乖乖寫上super(props)吧!

render為React Component一定要實作的的方法不然會報錯,會回傳一個使用JSX 生成的React Elements,每當props、state變化時就會觸發一次

明天會接著繼續介紹 Functional Component 與 Class Component 的差異


上一篇
[Day 05] React JSX - html 和JavaScript的完美結合
下一篇
[Day 07] Functional Component v.s Class Component
系列文
React初心者30天的探索之路30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言